﻿/**
 * project3D Engine
 * Ase loader
 * @author John Sword
 * @version 2 - AS3
*/

/*
 * Copyright 2006 (c) Carlos Ulloa Matesanz, noventaynueve.com.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

package engine.objects
{

	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.events.IOErrorEvent;
	import flash.net.URLRequest;
	import flash.net.URLLoader;
	import engine.objects.Object3D;
	import engine.geom.Face;
	import engine.geom.UV;
	import engine.geom.Vertex;
	import engine.geom.Vector;
	import engine.materials.Material;
	
	/**
	* load and parse a 3DS Max exported .ASE mesh.	*
	* Only the geometry and mapping of one mesh is currently parsed.
	*/
	public class Ase extends Object3D
	{
		
		//private var isInteractive:Boolean = false;
		private var flip:Boolean = false;
		private var _loaderAse :URLLoader;
		
		/**
		* Creates a new Ase object.
		* @param	filename	Filename of the .ASE object to parse.
		* @param	m			The object's material
		* @param	pos			Object position, defaults to 0,0,0.
		* @param	scale		Scaling vector, defaults to 1,1,1.
		* @param	fliptex		Whether to flip texture.
		*/
		public function Ase ( filename:String, m:Material, fliptex:Boolean = false )
		{
			super();
			this.objName = filename;
			this.flip = fliptex;
			this.material = m;
			this.flipNormals = true;
			loadAse();
		}
	
		/*
		public function setAsePosition ( v:Vector ) : void
		{
			position = v;
			transform_vertices ( null );
			//renderMe = true;
		}*/
	
		private function loadAse () : void
		{
			_loaderAse = new URLLoader();
			_loaderAse.addEventListener( Event.COMPLETE, parseAse, false, 0, true );
			_loaderAse.addEventListener( ProgressEvent.PROGRESS, progressHandler, false, 0, true);
			_loaderAse.addEventListener( IOErrorEvent.IO_ERROR, ioErrorHandler, false, 0, true);
	
	        var request:URLRequest = new URLRequest(objName);
	 
			try
			{
	            _loaderAse.load (request);
			}
			catch ( e:Error )
			{
				trace( "error in loading ase file. file not found?" );
			}
		}
			
			
		private function parseAse( e:Event ) : void
		{
			
			var vertices :Array = tVertices;
			var faces    :Array = faces;
			var loader:URLLoader = URLLoader(e.target);
			var lines: Array = unescape(loader.data).split( '\r\n' );

			var line: String;
			var chunk: String;
			var content: String;

			var uvs:Array = new Array();

			while( lines.length )
			{
				line = String( lines.shift() );

				//-- clear white space from beginn
				line = line.substr( line.indexOf( '*' ) + 1 );
	
				//-- clear closing brackets
				if( line.indexOf( '}' ) >= 0 ) line = '';
	
				//-- get chunk description
				chunk = line.substr( 0, line.indexOf( ' ' ) );

				switch( chunk )
				{
					case 'MESH_VERTEX_LIST':
						
						while( ( content = String( lines.shift() ) ).indexOf( '}' ) < 0 )
						{
							content = content.split("*")[1];

							var mvl: Array = content.split(  '\t' ); // separate here
							
							var x:Number =  Number( mvl[1] );
							var y:Number = -Number( mvl[2] ); // y points up
							var z:Number =  Number( mvl[3] ); // Swapped Y and Z??

							createVertex( new Vertex ( x, y, z ) );
						}
						
						break;


					case 'MESH_FACE_LIST':

						while( ( content = String( lines.shift() ) ).indexOf( '}' ) < 0 )
						{
							content = content.split("*")[1];

							var mfl: String = content.split('\t')[0]; // ignore: [MESH_SMOOTHING,MESH_MTLID]
							var drc: Array = mfl.split( ':' ); // separate here

							var con: String;
							con = drc[2]

							var a:Number = int( con.substr( 0, con.lastIndexOf( ' ' ) ) );
							con = drc[3];
							var b:Number = int( con.substr( 0, con.lastIndexOf( ' ' ) ) );
							con = drc[4];
							var c:Number = int( con.substr( 0, con.lastIndexOf( ' ' ) ) );
							createFace ( a, b, c, null,null,null, material );

						}
						
						break;


					case 'MESH_TVERTLIST':
						
						while( ( content = String( lines.shift() ) ).indexOf( '}' ) < 0 )
						{
							content = content.split("*")[1];

							var mtvl: Array = content.split(  '\t' ); // separate here
							uvs.push( new UV( Number( mtvl[1] ), Number( mtvl[2] ) ) );
						}
						
						break;


					case 'MESH_TFACELIST':		
						
						var num: int = 0;

						while( ( content = String( lines.shift() ) ).indexOf( '}' ) < 0 )
						{

							content = content.substr( content.indexOf( '*' ) + 1 );
							var mtfl: Array = content.split( '\t' ); // separate here
							
							faces[ num ].uv1 = uvs[ parseInt( mtfl[1] )] as UV;
							faces[ num ].uv2 = uvs[ parseInt( mtfl[2] )] as UV;
							faces[ num ].uv3 = uvs[ parseInt( mtfl[3] )] as UV;

							num++;

						}
						
						break;
				}
			}
			
			// set position
			//setAsePosition ( position );
			//transform_vertices( null );
			// set interactive
			if ( interactive ) setInteractive();
			
			// Remap UVs
			if ( material.texture )
			{
				var f:Face;
				var i:int = faces.length;
				while ( f = faces[--i] )
				{
					f.transformUV ( material.texture );
				}
			}

			renderMe = true;
			
			dispatchEvent ( new Event("LOAD") );
			
			trace ( "Parsed ASE: " + objName + "\n vertices:" + vertices.length + "\n faces:" + faces.length );

		}
		
		private function ioErrorHandler ( event:IOErrorEvent ) : void
		{
			//var fileEvent:FileLoadEvent = new FileLoadEvent( FileLoadEvent.LOAD_ERROR, filename );
			//dispatchEvent( fileEvent );
			trace ( objName + ": ASE File Loading Error" );
			//throw new Error("Ase: ioErrorHandler Error.");
		}
	
		private function progressHandler ( event:ProgressEvent ) : void
		{
			//trace(objName + " progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
		}
		
	}

}